package com.chauhai.android.batsg.mymap;

import android.graphics.Matrix;

/**
 * Matrix to manipulate the transformation of map image.
 * <p>
 * This is wrapper for <code>android.graphics.Matrix</code>.
 * It contains the <code>Matrix</code> object at heart.
 * @author umbalaconmeogia
 */
class MapImageMatrix {

  /**
   * The index of x movement when convert Matrix to float[]
   */
  private static final int MATRIX_LEFT = 2;

  /**
   * The index of y movement when convert Matrix to float[]
   */
  private static final int MATRIX_TOP = 5;

  /**
   * Zooming ratio. This always equals to matrix array [0].
   */
  private float zoomRatio = 1f;

  /**
   * The left-top position of the image bitmap on the view.
   */
  private Position leftTop = new Position(0, 0);

  Matrix matrix;

  public MapImageMatrix() {
    matrix = new Matrix();
  }

  /**
   * Get the zoom ratio.
   * @return
   */
  public float getZoomRatio() {
    return zoomRatio;
  }

  /**
   * Get the left-top position of the image.
   * @return
   */
  public Position getLeftTop() {
    return leftTop;
  }

  /**
   * Wrapper for {@link Matrix#setScale(float, float)}
   * @param ratio
   */
  public void setScale(float ratio) {
    if (ratio > 0) {
      this.zoomRatio = ratio;
      matrix.setScale(ratio, ratio);
    }
  }

  /**
   * This use {@link Matrix#postScale(float, float, float, float)} to set
   * the zoom ratio.
   * @param ratio
   * @param px
   * @param py
   */
  public void zoom(float ratio, float px, float py) {
    if (ratio > 0) {
      float scale = ratio / zoomRatio;
      matrix.postScale(scale, scale, px, py);
      zoomRatio = ratio;
    }
  }

  /**
   * Adjust the matrix.
   * <p>
   * If the zoomed image is smaller than the MapView, then make the
   * map image to be displayed at the center.
   * @param imageSize the bitmap image size.
   * @param width the MapView width.
   * @param height the MapView height.
   */
  public void adjustMatrix(Position imageSize, int width, int height) {
    // Export matrix to array.
    float[] matrixValues = new float[9];
    matrix.getValues(matrixValues);

    Position zoomedSize = imageSize.mult(zoomRatio); // New size.

    // Adjust the left position.
    if (zoomedSize.x < width) {
      // Image width is smaller than the view. Center horizontally.
      matrixValues[MATRIX_LEFT] = (width - zoomedSize.x) / 2;
    } else if (matrixValues[MATRIX_LEFT] > 0) {
      // Move to right over left border. Set left to 0.
      matrixValues[MATRIX_LEFT] = 0;
    } else if (matrixValues[MATRIX_LEFT] + zoomedSize.x < width) {
      // Move to left over right border. Set left to fit right.
      matrixValues[MATRIX_LEFT] = width - zoomedSize.x;
    }

    // Adjust the top position.
    if (zoomedSize.y < height) {
      // Image height is smaller than the view. Center vertically.
      matrixValues[MATRIX_TOP] = (height - zoomedSize.y) / 2;
    } else if (matrixValues[MATRIX_TOP] > 0) {
      // Mover to down over top border. Set top to 0.
      matrixValues[MATRIX_TOP] = 0;
    } else if (matrixValues[MATRIX_TOP] + zoomedSize.y < height) {
      // Move to up over bottom border. Set top to fit bottom.
      matrixValues[MATRIX_TOP] = height - zoomedSize.y;
    }

    // Apply float[] back to the matrix.
    matrix.setValues(matrixValues);

    // Set the left-top position of the map image.
    leftTop.set((int) matrixValues[MATRIX_LEFT],
        (int) matrixValues[MATRIX_TOP]);
  }
}
